﻿namespace DataDuctus.MongoDb.Serialization.Tests.Model
{
	using System.ComponentModel.DataAnnotations;
	using System.Runtime.Serialization;

	#region Primitive

	[DataContract]
	public class PrimitiveTypesPropertiesClass
	{
		[Key]
		[DataMember]
		public string Id { get; set; }

		[DataMember]
		public string StringProperty { get; set; }

		[DataMember]
		public int IntProperty { get; set; }

		[DataMember]
		public long LongProperty { get; set; }

		[DataMember]
		public double DoubleProperty { get; set; }

		[DataMember]
		public float FloatProperty { get; set; }

		[DataMember]
		public short ShortProperty { get; set; }

		[DataMember]
		public uint UIntProperty { get; set; }

		[DataMember]
		public ulong ULongProperty { get; set; }

		[DataMember]
		public ushort UShortProperty { get; set; }

		[DataMember]
		public byte ByteProperty { get; set; }

		[DataMember]
		public char CharProperty { get; set; }
	}

	[DataContract]
	public class PrimitiveTypesFieldsClass
	{
		public PrimitiveTypesFieldsClass(
			string stringProperty,
			int intProperty,
			long longProperty,
			double doubleProperty,
			float floatProperty,
			short shortProperty,
			uint uIntProperty,
			ulong uLongProperty,
			ushort uShortProperty,
			byte byteProperty,
			char charProperty)
		{
			this.stringProperty = stringProperty;
			this.intProperty = intProperty;
			this.longProperty = longProperty;
			this.doubleProperty = doubleProperty;
			this.floatProperty = floatProperty;
			this.shortProperty = shortProperty;
			this.uIntProperty = uIntProperty;
			this.uLongProperty = uLongProperty;
			this.uShortProperty = uShortProperty;
			this.byteProperty = byteProperty;
			this.charProperty = charProperty;
		}

		[Key]
		[DataMember]
		public string Id { get; set; }

		[DataMember]
		private string stringProperty;

		[DataMember]
		private int intProperty;

		[DataMember]
		private long longProperty;

		[DataMember]
		private double doubleProperty;

		[DataMember]
		private float floatProperty;

		[DataMember]
		private short shortProperty;

		[DataMember]
		private uint uIntProperty;

		[DataMember]
		private ulong uLongProperty;

		[DataMember]
		private ushort uShortProperty;

		[DataMember]
		private byte byteProperty;

		[DataMember]
		private char charProperty;
	}

	#endregion // Primitive

	#region One Inheritance

	[DataContract]
	[KnownType(typeof(OneInheritanceB))]
	public class OneInheritanceA
	{
		[Key]
		[DataMember]
		public string Id { get; set; }

		[DataMember]
		public string BaseName { get; set; }
	}

	[DataContract]
	public class OneInheritanceB : OneInheritanceA
	{
		[DataMember]
		public string SubClassName { get; set; }
	}

	[DataContract]
	[KnownType(typeof(OneInheritanceRegisterSubclassB))]
	public class OneInheritanceRegisterSubclassA
	{
		[Key]
		[DataMember]
		public string Id { get; set; }

		[DataMember]
		public string BaseName { get; set; }
	}

	[DataContract]
	public class OneInheritanceRegisterSubclassB : OneInheritanceRegisterSubclassA
	{
		[DataMember]
		public string SubClassName { get; set; }
	}
	#endregion // One Inheritance

	#region Single Level Composition
	[DataContract]
	public class SingleLevelCompositionMain
	{
		[Key]
		[DataMember]
		public string Id { get; set; }

		[DataMember]
		public SingleLevelCompositionComposite Composite { get; set; }
	}

	[DataContract]
	public class SingleLevelCompositionComposite
	{
		[DataMember]
		public string StringProperty { get; set; }
	}
	#endregion // Single Level Composition

	#region Single Level Composition One Inheritance
	#region Single Level Composition
	[DataContract]
	public class SingleLevelCompositionOneInheritanceMain
	{
		[Key]
		[DataMember]
		public string Id { get; set; }

		[DataMember]
		public SingleLevelCompositionOneInheritanceA Composite { get; set; }
	}
	#endregion // Single Level Composition

	#region Single Inheritance
	[DataContract]
	[KnownType(typeof(SingleLevelCompositionOneInheritanceB))]
	public class SingleLevelCompositionOneInheritanceA
	{
		[Key]
		[DataMember]
		public string Id { get; set; }

		[DataMember]
		public string BaseName { get; set; }
	}

	[DataContract]
	public class SingleLevelCompositionOneInheritanceB : SingleLevelCompositionOneInheritanceA
	{
		[DataMember]
		public string SubClassName { get; set; }
	}
	#endregion // Single Inheritance
	#endregion // Single Level Composition One Inheritance

	#region Multi Level Composition
	[DataContract]
	public class MulitLevelCompositionMain
	{
		[Key]
		[DataMember]
		public string Id { get; set; }

		[DataMember]
		public MulitLevelCompositionCompositeA Composite { get; set; }
	}

	[DataContract]
	public class MulitLevelCompositionCompositeA
	{
		[DataMember]
		public string StringProperty { get; set; }

		[DataMember]
		public MulitLevelCompositionCompositeB Composite { get; set; }
	}

	[DataContract]
	public class MulitLevelCompositionCompositeB
	{
		[DataMember]
		public string StringProperty { get; set; }

		[DataMember]
		public MulitLevelCompositionCompositeC Composite { get; set; }
	}

	[DataContract]
	public class MulitLevelCompositionCompositeC
	{
		[DataMember]
		public string StringProperty { get; set; }

		[DataMember]
		public MulitLevelCompositionCompositeD Composite { get; set; }
	}

	[DataContract]
	public class MulitLevelCompositionCompositeD
	{
		[DataMember]
		public string LastStringProperty { get; set; }
	}
	#endregion // Multi Level Composition

	#region Bastype Abstract Property Subclass With Decorated Override
	[KnownType(typeof(SubclassDecoratedOverride))] // TODO: Implement testcase for this Issiue#766
	[DataContract]
	public abstract class BaseTypeAbstractProperty
	{
		[Key]
		[DataMember]
		public string Id { get; set; }

		[DataMember(Name = "AbstractPropertyDecorated", IsRequired = true)]
		public abstract string AbstractPropertyDecorated { get; set; }
	}

	[DataContract]
	public class SubclassDecoratedOverride : BaseTypeAbstractProperty
	{
		[DataMember(Name = "AbstractPropertyDecorated", IsRequired = true)]
		public override string AbstractPropertyDecorated { get; set; }
	}
	#endregion // Bastype Abstract Property Subclass With Decorated Override

	#region KnownType for non inherited class gets misinterpreted
	[KnownType(typeof(TypeThatResidesInUnterminablePropertyType))]
	[DataContract]
	public class TypeContainingAnKnownTypeOfUndeterminablePropertyType
	{
		[Key]
		[DataMember]
		public string Id { get; set; }

		[DataMember]
		public object DataContractMappedType { get; set; }
	}

	[DataContract]
	public class TypeThatResidesInUnterminablePropertyType
	{
		[DataMember]
		public string HelloWorldProperty { get; set; }
	}
	#endregion // KnownType for non inherited class gets misinterpreted
}
